import operator
import time
from osv import osv, fields
from osv.orm import intersect
import tools.sql
from tools import config
from tools.translate import _
from mx import DateTime
import netsvc
from tools.amount_to_text import amount_to_text

class kderp_other_expense(osv.osv):
    _name = 'kderp.other.expense'
    _description = 'KDERP Other Expense'
    
    def unlink(self, cr, uid, ids, context=None):
        if ids:
            payment_id = ",".join(map(str,ids))
            for rop in self.read(cr,uid,ids,['state']):
                if rop['state'] not in ('draft'):
                    raise osv.except_osv("KDERP Warning !","You can delete Other Expense with status in Draft only")
        unlink_ids = ids
        return super(kderp_other_expense, self).unlink(cr, uid, unlink_ids, context=context)
    
    def write(self, cr, uid, ids, vals, context=None):
        self.pool.get('ir.rule').domain_get.clear_cache(cr.dbname)
        return osv.osv.write(self, cr, uid, ids,vals,context=context)

    def fields_get(self, cr, uid, fields=None, context=None):
        res = super(kderp_other_expense, self).fields_get(cr, uid, fields, context)
        new_field={'search_in_line_budget':
                                        {'widget':u'char',
                                         'type':u'char',
                                         'name':u'search_in_line_budget',
                                         'select': u'1',
                                         'string':u'Budget No',
                                         'invisible':True,
                                         'visible':False,
                                         'size':128,
                                         'sql':"(Select distinct other_expense_id from kderp_other_expense_line left join account_budget_post abp on budget_id=abp.id where abp.name || ' ' || abp.code ilike chr(37) || '%s' || chr(37))"}}
        res.update(new_field)
        return res

    
    def _exrate(self, cr, uid, ids, name, arg, context={}):
        res = {}
        if ids:
            cr.execute("Select id,\
                                fncompute(currency_id,get_default_currency(),date,'tax_office')\
                        from kderp_other_expense po where id in (%s) " % ",".join(map(str, ids)))
        for po_id, rate in cr.fetchall():
            res[po_id] = rate
        for obj_id in ids:
            res.setdefault(obj_id, 0.0)
        for id in ids:
            res[id] = res.get(id, 0.0)
        return res

    def _get_budgetcode_inline(self,cr,uid,ids,name,arg,context={}):
        res = {}
        if ids:
            ot_ids = ",".join(map(str,ids))
            cr.execute("""Select 
                                id,
                                sum(code || ',') 
                        from
                                kderp_other_expense koe
                        left join
                                kderp_other_expense_line koel on koe.id = koel.other_expense_id
                        left join
                                account_budget_post abp on budget_id = abp.id
                         where koe.id in (%s) group by po.id""" % ot_ids)
            budgets =  cr.fetchall()
            for id,budget in budgets:
                if budget:
                    tmp = budget.strip()
                    tmp = tmp[:len(tmp)-1]
                    res[id] = tmp
                else:
                    res[id] = budget            
        return res
    
    def _new_code_other_expense(self, cr, uid, context):
        new_code = False        
        code_type = 'action_other_expense'
        cr.execute("""Select
                         prefix || 
                         to_char(current_date,suffix) || 
                         lpad((max(substring(current_code from length(prefix ||suffix)+1 for padding)::integer)+1)::text,padding,'0') as new_code
                    from
                        (Select
                            case when 
                            po.name is null 
                            then 
                            prefix || to_char(current_date,suffix) || lpad('0',padding,'0')  else po.name end as current_code,
                            padding,
                            suffix,
                            prefix,current_date
                        from 
                            ir_sequence isq
                        left join
                            kderp_other_expense po on po.name ilike prefix || to_char(current_date,suffix) || lpad('_',padding,'_')
                        where 
                            code='%s' and isq.active) vwcurrent_code
                    group by
                        padding,
                        suffix,
                        prefix,
                        current_date;""" %(code_type))
        res = cr.fetchone()
        if res:
            new_code=res[0]            
        return new_code
    
    def _get_ot_line(self, cr, uid, ids, context={}):
        result = {}
        for line in self.pool.get('kderp.other.expense.line').browse(cr, uid, ids, context=context):
            result[line.other_expense_id.id] = True
        return result.keys()
    
    def _new_project_id(self, cr, uid, context):
        prj_id = False
        if context:
            if 'prj_context_id' in context:
                prj_id = context['prj_context_id']
        return prj_id
    
    #Other Expense Area
    def action_draft_done_other_expense(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'done'})
        return True
        
    def action_other_expense_cancel(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'cancel'})
        return True
    
    def action_ot_open(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'draft'})
        return True
    
    def action_other_expense_revise(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'draft'})
        return True
    
    def _get_amount_other_expense(self, cr, uid, ids, name, args, context={}):
        res = {}
        for ot_obj in self.browse(cr,uid,ids):
            subtotal = 0
           # raise osv.except_osv("E",ot_obj.other_expense_line)
            tax_amount = 0
            for otl in ot_obj.other_expense_line:
                subtotal = subtotal + otl.amount
            tax_amount = subtotal * ot_obj.tax_per/100.0
            val={}
            if abs(ot_obj.tax_amount-tax_amount)<2:
                tax_amount = ot_obj.tax_amount
            cr.execute("Update kderp_other_expense set tax_amount=%s where id in (%s)" %(tax_amount,ot_obj.id))
            res[ot_obj.id]={'total_amount':subtotal + tax_amount,'sub_total':subtotal}
        return res
    
    _columns={
        'name': fields.char('Exp. No.', size=64, required=True, select=True,states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        'description': fields.text('Description',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'date':fields.datetime('Exp. Date', required=True, states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'user_id': fields.many2one('res.users', 'User request',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),    
        'project_id':fields.many2one('kdvn.project','Project',states={'done':[('readonly',True)], 'cancel':[('readonly',True)]},select=1),
        'currency_id':fields.many2one('kderp.currency','Cur.',required=True,states={'done':[('readonly',True)], 'cancel':[('readonly',True)]},context={'typeofrate':'tax_office'}),        
        
        'state':fields.selection([('draft','Draft'),('cancel','Cancel'),('done','Done')],'Status',readonly='True'),
        
        'sub_total':fields.function(_get_amount_other_expense,string='Sub-Total',type='float',method=True,multi='_get_ot_from_line',
                                         store={
                                                'kderp.other.expense.line': (_get_ot_line, None, 10),
                                                'kderp.other.expense':(lambda self, cr, uid, ids, c={}: ids, None, 20)}),
              
        'tax_per':fields.float("VAT (%)",states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),#"VAT (%)",states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}
        'tax_amount':fields.float('Tax Amount',digits=(16,2),states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'total_amount':fields.function(_get_amount_other_expense,string='Total Amt',type='float',method=True,multi='_get_ot_from_line',
                                         store={
                                                'kderp.other.expense.line': (_get_ot_line, None, 10),
                                                'kderp.other.expense':(lambda self, cr, uid, ids, c={}: ids, None, 20)}),
        
        'other_expense_line':fields.one2many('kderp.other.expense.line','other_expense_id', 'Expense Lines', states={'done':[('readonly',True)], 'cancel':[('readonly',True)]}),
        
        'exrate':fields.function(_exrate,method=True,string="Ex.Rate",type='float'),
        'budget_codes':fields.function(_get_budgetcode_inline,method=True,type='char',size=250,string='Budget'),
        }
    _sql_constraints = [('other_expense_number_unique', 'unique (name)', 'KDERP Error: The number of the other expense must be unique !')]
    _order = "name"    
    _defaults={
              'user_id':lambda obj,cr,uid,context: uid,
              'project_id':_new_project_id,
              'name':_new_code_other_expense,
              'tax_per':lambda *x:10,
              'tax_amount':lambda *x:0.0,
              'state':lambda *x:'draft',
              'date':lambda *x:time.strftime('%Y-%m-%d %H:%M:%S')
              }
    def on_tax_percent_change(self, cr, uid, id, tax_per,amount,tax_amount=False):
        order_amount=amount or 0.0
        tax_per=tax_per or 0
        if tax_amount:
            total_amount=tax_amount+order_amount
        else:
            tax_amount=tax_per*order_amount/100.0        
            total_amount=tax_amount+order_amount
        #raise osv.except_osv("Error",order_amount)
        return {'value':{'tax_amount':tax_amount,'total_amount':total_amount}} 
kderp_other_expense()

class kderp_other_expense_line(osv.osv):
    _name = 'kderp.other.expense.line'
    _description = 'KDERP Other Expense Line'

    def new_budget_id(self, cr, uid, context={}):
        budget_id = False
        if context:
            if 'order_id' in context:
                order_id = context['order_id']
                cr.execute("Select budget_id from kderp_other_expense_line pol where other_expense_id=%s order by id desc limit 1" % order_id)
                new_product_obj = cr.fetchone()
                budget_id =False
                if new_product_obj:
                    budget_id = new_product_obj[0]
        return budget_id
    
    _columns={

            'budget_id': fields.many2one('account.budget.post', 'Budget',required=True),  
            'name': fields.char('Description', size=256),
            'amount': fields.float('Amount'),
            'other_expense_id':fields.many2one('kderp.other.expense','Other Expense',required=True, ondelete='cascade'),         
        }
#    _sql_constraints = [('budget_doesnot_exist_other_expense', 'CHECK (fn_check_constraint_project_budget_ot(budget_id,other_expense_id))',  'KDERP Error: The budget code of the Job does not exists !')]
    _order = "other_expense_id"
    _defaults = {
        'budget_id':new_budget_id,
        'amount':lambda *x:0,
        }

kderp_other_expense_line()


class kderp_other_expense_for_budget_summary(osv.osv):
    _description='KDERP Other Expense for Budget Summary'
    _name = 'kderp.other.expense.for.budget.summary'
    _auto = False
    
    _columns = {
                'other_expense_id':fields.many2one('kderp.other.expense','Exp. No.'),
                'description':fields.text("Description"),
                'exp_amount':fields.float("Amount"),
                'exp_amount_idr':fields.float("Amount (In Rp.)"),
                }
    def init(self,cr):
        cr.execute("""create or replace view kderp_other_expense_for_budget_summary as
                    Select
                        row_number() over (order by other_expense_id,project_id,budget_id) as id,
                        *
                    from
                        (Select
                            koe.id as other_expense_id,
                            description,
                            koe.project_id,
                            budget_id,
                            sum(amount) as exp_amount,
                            sum(fncompute(currency_id,get_default_currency(),date,'tax_office')*amount) as exp_amount_idr
                        from
                            kderp_other_expense koe
                        left join
                            kderp_other_expense_line koel on koe.id = other_expense_id
                        where
                            state not in ('draft','cancel')
                        Group by
                            project_id,
                            budget_id,
                            koe.id) vwcombined""")
kderp_other_expense_for_budget_summary()
